Learn through the super-clean Baeldung Pro experience:
>> Membership and Baeldung Pro.
No ads, dark-mode and 6 months free of IntelliJ Idea Ultimate to start with.
Last updated: March 26, 2025
In Docker, developers can build, deploy, and test applications by packaging them in a container along with all of their dependencies. Docker Compose is an essential tool for managing many containers using services.
In this tutorial, we’ll understand how to execute multiple commands in a Docker container, managed using Docker Compose. Additionally, we’ll explore different ways to run multiple commands in the Docker container.
Docker Compose enables us to execute commands inside a Docker container. We can set any command to run during the container startup via the command instruction.
Let’s take a look at a docker-compose.yml, which runs a simple command inside a container:
version: "3"
services:
server:
image: alpine
command: sh -c "echo "baeldung""
In the above docker-compose.yml file, we execute a single echo command inside the alpine Docker image.
Of course, we can use Docker Compose to manage more than one application by creating services in the docker-compose.yml file. Let’s take a look at how to run multiple commands.
We start by creating a simple docker-compose.yml file to demonstrate how the Docker Compose configuration runs more than one command:
version: "3"
services:
server:
image: alpine
command: sh -c "echo "baeldung" && echo "docker" "
Here, we used alpine as the base image for the Docker container. Notably, we execute two commands in the last line: echo baeldung and echo docker, split by the && operator.
To demonstrate the result, let’s run this image using the docker-compose up command:
$ docker-compose up
Creating dockercompose_server_1 ... done
Attaching to dockercompose_server_1
server_1 | baeldung
server_1 | docker
dockercompose_server_1 exited with code 0
Here, the output of both echo statements goes to stdout.
We can also use the | operator to run multiple commands in Docker Compose. The syntax of the | operator is a bit different from the && operator.
To illustrate how the | operator works, let’s update the docker-compose.yml:
version: "3"
services:
server:
image: alpine
command:
- /bin/sh
- -c
- |
echo "baeldung"
echo "docker"
Everything is the same except for the command instruction. Here, we added the commands on separate lines. Thus, this approach is recommended as it keeps the YAML file neater since each command is on a separate line.
Let’s again run the Docker container with the docker-compose up command:
$ docker-compose up
Creating dockercompose_server_1 ... done
Attaching to dockercompose_server_1
server_1 | baeldung
server_1 | docker
dockercompose_server_1 exited with code 0
As we can see from the above output, both commands run one by one.
When we have a series of commands that we need to execute in a specific order or want to reuse across multiple services, a shell script provides a clean and organized solution.
We can bundle all the commands into a single script, include it in the Docker image, and then execute it using Docker Compose.
Let’s say we have a script called script.sh:
$ cat script.sh
#!/bin/sh
echo "Setting up the environment..."
mkdir -p /app/data
cp /tmp/config.ini /app/config/
echo "Starting the application..."
python /app/main.py
Thus, we can include this script in the Dockerfile and make it executable:
$ cat Dockerfile
FROM python:3.9-slim-buster
WORKDIR /app
COPY . .
COPY script.sh /app/script.sh
RUN chmod +x /app/script.sh
CMD ["/app/script.sh"]
Finally, in the docker-compose.yml, we reference the script as the command for the service:
$ cat docker-compose.yml
version: '3'
services:
myapp:
build: .
command: /app/script.sh
Now, when we run docker-compose up, Docker Compose executes script.sh and runs all the commands within it sequentially.
While shell scripts are great for Linux-based environments, we need a different approach when working with Windows containers.
In these cases, we can use a .bat file to bundle commands. It’s essentially the Windows equivalent of a shell script.
For example, if we have a .bat file named setup.bat:
@echo off
echo "Setting up the Windows environment..."
mkdir C:\app\data
copy C:\temp\config.ini C:\app\config\
echo "Starting the application..."
C:\app\myapp.exe
We can include this file in the Docker image during the build process, similar to how we included shell scripts:
FROM mcr.microsoft.com/windows/servercore:ltsc2022
WORKDIR /app
COPY . .
COPY setup.bat C:\app\setup.bat
CMD ["C:\\app\\setup.bat"]
In the docker-compose.yml, we then reference the .bat file as the command for the service:
version: '3'
services:
myapp:
build: .
command: C:\app\setup.bat
Therefore, when we run docker-compose up, Docker Compose executes the setup.bat file.
Executing multiple commands within a Docker Compose file offers several advantages:
In conclusion, executing multiple commands in Docker Compose empowers us with greater control and flexibility in managing containerized applications.
In this article, we explored various methods for executing multiple commands in a Docker Compose environment. We started with simpler techniques using the && and | operators, then moved on to more organized approaches with shell scripts and batch files.